/* eslint-disable no-shadow */
import { IControl, IPanelCtrlPos } from '@ibiz/model-core';
import {
  Method,
  AppDataEntity,
  getControlsByView,
  IControlController,
  calcDeCodeNameById,
  PanelItemController,
} from '@ibiz-template/runtime';
import {
  ITabItem,
  PanelCtrlPosTabExpState,
} from './panel-ctrl-pos-tab-exp.state';

/**
 * @description 面板部件占位分页导航控制器
 * @export
 * @class PanelCtrlPosTabExpController
 * @extends {PanelItemController<IPanelCtrlPos>}
 */
export class PanelCtrlPosTabExpController extends PanelItemController<IPanelCtrlPos> {
  /**
   * @description 状态
   * @type {PanelCtrlPosTabExpState}
   * @memberof PanelCtrlPosTabExpController
   */
  declare state: PanelCtrlPosTabExpState;

  /**
   * @description 部件控制器集合
   * @type {IControlController}
   * @memberof PanelCtrlPosTabExpController
   */
  controlMap: Map<string, IControlController> = new Map();

  /**
   * @description 默认部件模型
   * @type {IControl}
   * @memberof PanelCtrlPosTabExpController
   */
  defaultModel?: IControl;

  /**
   * @description 部件名称属性
   * @type {string}
   * @memberof PanelCtrlPosTabExpController
   */
  ctrlNameField?: string;

  /**
   * @description 部件映射
   * @type {IData}
   * @memberof PanelCtrlPosTabExpController
   */
  ctrlMap?: IData;

  /**
   * @description 新建状态
   * @protected
   * @returns {*}  {PanelCtrlPosTabExpState}
   * @memberof PanelCtrlPosTabExpController
   */
  protected createState(): PanelCtrlPosTabExpState {
    return new PanelCtrlPosTabExpState(this.parent?.state);
  }

  /**
   * @description 初始化
   * @returns {*}  {Promise<void>}
   * @memberof PanelCtrlPosTabExpController
   */
  async onInit(): Promise<void> {
    await super.onInit();
    this.defaultModel = this.getCtrlModelByName(this.model.id!);
    try {
      const ctrlParams = this.defaultModel?.controlParam?.ctrlParams;
      if (ctrlParams?.CTRLNAMEFIELD)
        this.ctrlNameField = ctrlParams.CTRLNAMEFIELD;
      if (ctrlParams?.CTRLMAP) this.ctrlMap = JSON.parse(ctrlParams.CTRLMAP);
    } catch (error) {
      ibiz.log.error(error);
    }
  }

  /**
   * @description 通过部件名称获取部件模型
   * @private
   * @param {string} name
   * @returns {*}  {(IControl | undefined)}
   * @memberof PanelCtrlPosTabExpController
   */
  private getCtrlModelByName(name: string): IControl | undefined {
    const controls = getControlsByView(this.panel.view.model);
    return controls.find(ctrl => ctrl.name === name);
  }

  /**
   * @description 绑定部件控制器
   * @param {IControlController} controller
   * @returns {*}  {void}
   * @memberof PanelCtrlPosTabExpController
   */
  bindControl(controller: IControlController): void {
    const { activeTabKey } = this.state;
    if (!activeTabKey) return;
    this.controlMap.set(activeTabKey, controller);
    controller.evt.onAll((eventName, event) => {
      this.panel.evt.emit('onControlEvent', {
        triggerControlName: controller.model.name!,
        triggerEventName: eventName,
        triggerEvent: event,
      });
    });
  }

  /**
   * @description 获取部件模型
   * @private
   * @param {AppDataEntity} data
   * @returns {*}  {(IControl | undefined)}
   * @memberof PanelCtrlPosTabExpController
   */
  private getCtrlModel(data: AppDataEntity): IControl | undefined {
    if (this.ctrlNameField && this.ctrlMap) {
      const ctrlName = this.ctrlMap[data[this.ctrlNameField]];
      return this.getCtrlModelByName(ctrlName);
    }
    return this.defaultModel;
  }

  /**
   * @description 添加分页导航
   * @param {AppDataEntity} data 分页数据
   * @returns {*}  {Promise<void>}
   * @memberof PanelCtrlPosTabExpController
   */
  async addTabNav(data: AppDataEntity): Promise<void> {
    const ctrlModel = this.getCtrlModel(data);
    const appDataEntityId = ctrlModel?.appDataEntityId;
    if (!appDataEntityId) return;
    const appDataEntityCodeName = calcDeCodeNameById(appDataEntityId);
    // 界面域标识
    const key = data.srfkey;
    // 如果已经存在则直接切换激活项
    if (ibiz.uiDomainManager.has(key)) {
      this.state.activeTabKey = key;
      return;
    }
    const context = Object.assign(this.panel.context.clone(), {
      [appDataEntityCodeName]: key,
      srfsessionid: key,
    });
    const params = { ...this.panel.params };
    // 创建数据域
    ibiz.uiDomainManager.create(key, appDataEntityId);
    // 获取实体服务
    const app = ibiz.hub.getApp(context.srfappid);
    const deService = await app.deService.getService(context, appDataEntityId);
    // 添加数据缓存
    const result = await deService.exec('CreateTemp', context, data);
    if (result.ok && result.data) {
      const method: Method = await (deService as IData).getMethod('GetTemp');
      // 根据dto设置子数据缓存
      await (method.result as IData).dto?.sets(context, [data]);
      const item: ITabItem = {
        params,
        context,
        ctrlModel,
        id: data.srfkey,
        name: data.srfmajortext,
      };
      this.state.tabs.push(item);
      this.state.cacheKeys.push(item.id);
      this.state.activeTabKey = item.id;
    }
  }

  /**
   * @description 删除分页导航
   * @param {string} id
   * @returns {*}  {void}
   * @memberof PanelCtrlPosTabExpController
   */
  removeTabNav(id: string): void {
    const { tabs, activeTabKey } = this.state;

    // 使用 findIndex 查找标签页索引
    const tabIndex = tabs.findIndex(tab => tab.id === id);
    if (tabIndex === -1) return;

    // 处理激活标签页的切换逻辑
    if (activeTabKey === id) this.handleActiveTabChange(tabIndex, tabs);

    // 移除标签页和缓存键
    this.removeTabAndCache(id);
  }

  /**
   * @description 删除其它导航页
   * @memberof PanelCtrlPosTabExpController
   */
  removeOtherTabNav(): void {
    const { activeTabKey } = this.state;
    const keys = this.state.tabs
      .filter(tab => tab.id !== activeTabKey)
      .map(tab => tab.id);
    keys.forEach(key => this.removeTabAndCache(key));
  }

  /**
   * @description 删除所有导航页
   * @memberof PanelCtrlPosTabExpController
   */
  removeAllTabNav(): void {
    const keys = this.state.tabs.map(tab => tab.id);
    keys.forEach(key => this.removeTabAndCache(key));
  }

  /**
   * @description 处理激活标签页的切换
   * @private
   * @param {number} currentIndex
   * @param {ITabItem[]} tabs
   * @memberof PanelCtrlPosTabExpController
   */
  private handleActiveTabChange(currentIndex: number, tabs: ITabItem[]): void {
    const nextTab = tabs[currentIndex + 1] || tabs[currentIndex - 1];
    this.state.activeTabKey = nextTab?.id;
  }

  /**
   * @description 移除标签页和对应的缓存键
   * @private
   * @param {string} id
   * @memberof PanelCtrlPosTabExpController
   */
  private removeTabAndCache(id: string): void {
    // 移除标签页
    const index = this.state.tabs.findIndex(tab => tab.id === id);
    if (index === -1) return;
    const { context } = this.state.tabs[index];
    this.state.tabs.splice(index, 1);
    // 销毁数据域
    ibiz.uiDomainManager.destroy(context.srfsessionid);
    // 移除控制器
    if (this.controlMap.has(id)) this.controlMap.delete(id);
    // 移除缓存键
    const cacheIndex = this.state.cacheKeys.findIndex(key => key === id);
    if (cacheIndex !== -1) this.state.cacheKeys.splice(cacheIndex, 1);
  }

  /**
   * @description 销毁
   * @memberof PanelCtrlPosTabExpController
   */
  destroy(): void {
    this.removeAllTabNav();
  }
}
